import GameCtrl from '../controller/GameCtrl';
import { GameState } from '../define/GameDefine';
import { UICommandKey } from '../define/UICommand';
import ViewMgr from '../manager/ViewMgr';
import PlayerModel from '../model/PlayerModel';
import RandomTool from '../tool/RandomTool';

export enum SendDataType {
  /**
   * 开始游戏
   */
  NewGame,
  /**
   * 确认数据初始化完毕
   */
  ConfirmInit,
  /**
   * 操作数据
   */
  OperationData,
}

export enum ReceivedDataType {
  /**
   * 游戏创建成功，下发随机种子（两个）。定义不同的客户端 id。
   */
  GameCreated = 1,
  /**
   * 游戏正式开始，开始进入主循环。
   */
  GameStart = 2,
  /**
   * 帧数据
   */
  FrameData = 3,
  /**
   * 游戏结束
   */
  GameEnd = 4,
}

export class WebSocketClient {
  private ws;

  public connected: Promise<void>;

  private messageHandlers = {
    [ReceivedDataType.GameCreated]: (data: any) => {
      this.onFindGame(data);
    },
    [ReceivedDataType.GameStart]: (data: any) => {},
    [ReceivedDataType.FrameData]: (data: any) => {
      this.onGetData(data);
    },
    [ReceivedDataType.GameEnd]: (data: any) => {},
  };

  constructor(ip: string) {
    //118.25.36.178:10000
    this.ws = new WebSocket('ws://' + ip + ':10000');
    const ws = this.ws;
    this.connected = new Promise((resolve) => {
      ws.addEventListener('open', () => {
        resolve();
      });
    });

    ws.addEventListener('message', this.onMessage);
    ws.addEventListener('error', this.onError);
    ws.addEventListener('close', this.onClose);
  }

  /**
   * 寻找游戏 开始游戏
   * @param name
   */
  findGame(name: string) {
    this.sendMessage(SendDataType.NewGame, { name: name });
  }

  onFindGame(data: any) {
    RandomTool.arr_init(data.randomSeeds);
    GameCtrl.inst.mapInit();
    GameCtrl.inst.createPlayer(data.playersData);
    ViewMgr.ins.emit(UICommandKey.onFindGame);
    this.frameList = [];
    GameCtrl.inst.state = GameState.Run;
    this.confirmData();
  }

  confirmData() {
    this.sendMessage(SendDataType.ConfirmInit);
  }

  /**
   * 发送操作
   */
  sendOperation(op: any) {
    this.sendMessage(SendDataType.OperationData, op);
  }

  public frameList: any[];
  onGetData(data: any) {
    this.frameList.push(...Object.values(data));
  }

  private onMessage = (msg: MessageEvent) => {
    const { type, data } = JSON.parse(msg.data) as any;
    // console.log(type);
    // console.log(data);
    // @ts-ignore
    this.messageHandlers[type](data);
  };

  private onError = (err: Event) => {
    console.log(err);
  };

  private onClose = () => {
    console.log(`close`);
  };

  private sendMessage(type: number, data?: any) {
    const msg = { type, data };
    this.ws.send(JSON.stringify(msg));
  }
}
